
package cn.klandor.picasa.ui;

import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

import cn.klandor.picasa.util.Photo;

public class PhotoChooser extends JPanel {
	
	private static final long serialVersionUID = 1L;
	private int photoIndex;
	private String photoInfo;
	
	private ArrayList<Photo> listPhotos = null;
	private ArrayList<Photo> showPhotos = null;
	private Dimension oldDimension = new Dimension(0,0);
	
	private int photoSpacing = 2;
	private int photoWidth = 40;
	private int photoHeight = 40;
	private int photoHeight_2 = 80;
	private int photoInfo_y = 10;
	private int photo_y = 15;

	private PhotoPanel photoPanel;
	
	public PhotoChooser(PhotoPanel photoPanel){
		
		setLayout(new GridBagLayout());
		this.photoPanel = photoPanel;
		this.listPhotos = null;
		addMouseListener(new PhotoClickedListener());
        addMouseWheelListener(new MouseWheelScroller());
	}

	
	public Dimension getPreferredSize() {
        return new Dimension(400, 70);
    }

    public boolean isFocusable() {
        return true;
    }

	public void paintComponent(Graphics g) {
		super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                            RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        Composite oldComposite = g2.getComposite();

        try {
			if(oldDimension != getSize()){
				showPhotos = getShowPhotos(listPhotos ,getWidth(),photoIndex);
				oldDimension = getSize();
			}
			if (showPhotos!= null) {
	        	drawPhotoInfos(g2);
	        	drawPhotos(g2, showPhotos);
	        }
		} catch (Exception e) {
			e.printStackTrace();
		}
        
        g2.setComposite(oldComposite);
    }

	private void drawPhotos(Graphics2D g2, List<Photo> showPhotos) {
        for (Photo photo: showPhotos) {
            g2.drawImage(photo.getImgIcon(),
                         photo.getPosition_x(), photo_y,
                         photoWidth, photoHeight_2, null);
        }
    }
	
	private void drawPhotoInfos(Graphics2D g2) {
        Composite composite = g2.getComposite();

        FontRenderContext context = g2.getFontRenderContext();
        Font font = new Font("Arial", Font.BOLD, 14);
        TextLayout layout = new TextLayout(photoInfo, font, context);
        Rectangle2D bounds = layout.getBounds();
        int text_x = (int) ((getWidth() - bounds.getWidth()) / 2);
        int text_y = photoInfo_y;

        g2.setColor(Color.WHITE);
        layout.draw(g2, text_x, text_y);
        
        g2.setComposite(composite);
    }
	
	public List<Photo> getListPhotos() {
		return listPhotos;
	}

	public void setListPhotos(ArrayList<Photo> listPhotos) {
		this.listPhotos = listPhotos;
		setPhotoIndex(listPhotos.size()/2);
	}

	public PhotoPanel getPhotoPanel() {
		return photoPanel;
	}

	public void setPhotoPanel(PhotoPanel photoPanel) {
		this.photoPanel = photoPanel;
	}
	
	public int getPhotoIndex() {
		return photoIndex;
	}

	public void setPhotoIndex(int Index) {
		this.photoIndex = Index;
		if(photoIndex <0 || listPhotos== null) {
			photoIndex = 0;
			return;
		}
		if(photoIndex >= listPhotos.size()) {
			photoIndex = listPhotos.size()-1;
			return;
		}
		try {
			photoInfo = listPhotos.get(photoIndex).getPhotoName()
						+" ("+listPhotos.get(photoIndex).getWidth()
						+"X"+listPhotos.get(photoIndex).getHeight()
						+")";
			photoPanel.setImg(ImageIO.read(listPhotos.get(photoIndex).getOriginalPhotoURL()));
		} catch (IOException e) {
			e.printStackTrace();
		}
		repaint();
	}
	// get the Draw Photo List
	public ArrayList<Photo> getShowPhotos(List<Photo> listPhotos ,int width, int photoIndex) throws Exception {
		int photo_x = 0;
		Photo myPhoto = null;
		ArrayList<Photo> drawablePhotos = new ArrayList<Photo>();
		if(listPhotos == null){
			return null;
		}
		for (int index = 0; index < listPhotos.size(); index++) {
			photo_x = ((width - photoWidth) / 2)+((index-photoIndex) *(photoWidth+photoSpacing));
			if (photo_x >= width || photo_x < -photoWidth) {
				;
			}else{
				myPhoto = listPhotos.get(index);
				myPhoto.setIndex(index);
				myPhoto.setPosition_x(photo_x);
				
				drawablePhotos.add(myPhoto);
		    }
		}
		return drawablePhotos;
	}
	
	
	private void scrollAndAnimateBy(int increment) {
		
		if (listPhotos == null) return;
		int index = photoIndex + increment;
		if (index < 0) {
        	index = 0;
		} else if (index >= listPhotos.size()) {
			index = listPhotos.size() - 1;
      	}
      	for (Photo photo: showPhotos) {
        	if (photo.getIndex() == index) {
            	setPhotoIndex(photo.getIndex());
            	break;
        	}
      	}
	}
	
	private class MouseWheelScroller implements MouseWheelListener {
        public void mouseWheelMoved(MouseWheelEvent e) {
            int increment = e.getWheelRotation();
            scrollAndAnimateBy(increment);
        }
    }

    private class PhotoClickedListener extends MouseAdapter {
        
        public void mouseClicked(MouseEvent e) {
            if (showPhotos == null) {
                return;
            }
            if (e.getButton() == MouseEvent.BUTTON1) {
                Photo photo = getHitPhoto(e.getX(), e.getY());
                if (photo != null && photo.getIndex() != photoIndex) {
                	setPhotoIndex(photo.getIndex());
                }
            }
        }
    }

	public Photo getHitPhoto(int x, int y) {
		for (Photo photo: showPhotos) {
            Rectangle hit = new Rectangle(photo.getPosition_x(), photo_y,photoWidth, photoHeight);
            if (hit.contains(x, y)) {
                return photo;
            }
        }
		return null;
	}
	
	public boolean isOpaque() {
        return false;
    }
    
}
